/**
 * Copyright (c) 2018-2028, Joffee.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.sailmi.system.service.impl;

import com.alibaba.nacos.plugin.auth.constant.Constants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sailmi.common.constant.AppConstant;
import com.sailmi.common.model.auth.AuthInfo;
import com.sailmi.common.model.auth.AuthUser;
import com.sailmi.common.tool.node.ForestNodeMerger;
import com.sailmi.common.tool.support.Kv;
import com.sailmi.common.tool.utils.Func;
import com.sailmi.common.tool.utils.SecureUtil;
import com.sailmi.common.tool.utils.StringUtil;
import com.sailmi.system.entity.SystemEntity;
import com.sailmi.system.service.ISystemService;
import com.sailmi.system.dto.MenuDTO;
import com.sailmi.system.entity.Menu;
import com.sailmi.system.entity.RoleMenu;
import com.sailmi.system.mapper.MenuMapper;
import com.sailmi.system.service.IMenuService;
import com.sailmi.system.service.IRoleMenuService;
import com.sailmi.system.vo.MenuVO;
import com.sailmi.system.wrapper.MenuWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author Joffee
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
	@Resource
	IRoleMenuService roleMenuService;
	@Resource
	ISystemService systemService;


	@Override
	public IPage<MenuVO> selectMenuPage(IPage<MenuVO> page, MenuVO menu) {
		return page.setRecords(baseMapper.selectMenuPage(page, menu));
	}

	@Override
	public List<MenuVO> routes(String roleId) {
		List<Menu> allMenus = baseMapper.allMenu();
		List<Menu> roleMenus = baseMapper.roleMenu(Func.toLongList(roleId));
		List<Menu> routes = new LinkedList<>(roleMenus);
		roleMenus.forEach(roleMenu -> recursion(allMenus, routes, roleMenu));
		routes.sort(Comparator.comparing(Menu::getSort));
		MenuWrapper menuWrapper = new MenuWrapper();
		List<Menu> collect = routes.stream().filter(x -> Func.equals(x.getCategory(), 1)).collect(Collectors.toList());
		return menuWrapper.listNodeVO(collect);
	}



	@Override
	public List<MenuVO> routes(int consoleType,String roleId) {
		if (StringUtil.isBlank(roleId)) {
			return null;
		}
		List<Menu> allMenus = baseMapper.allMenu();
		List<Menu> roleMenus = baseMapper.roleMenu(Func.toLongList(roleId));
		List<Menu> routes = new LinkedList<>(roleMenus);
		roleMenus.forEach(roleMenu -> recursion(allMenus, routes, roleMenu));
		routes.sort(Comparator.comparing(Menu::getSort));
		MenuWrapper menuWrapper = new MenuWrapper();
		List<Menu> collect = routes.stream().filter(x -> Func.equals(x.getCategory(), 1)&&Func.equals(x.getAdminFlag(),consoleType)).collect(Collectors.toList());
		return menuWrapper.listNodeVO(collect);
	}

	public void recursion(List<Menu> allMenus, List<Menu> routes, Menu roleMenu) {
		Optional<Menu> menu = allMenus.stream().filter(x -> Func.equals(x.getId(), roleMenu.getParentId())).findFirst();
		if (menu.isPresent() && !routes.contains(menu.get())) {
			routes.add(menu.get());
			recursion(allMenus, routes, menu.get());
		}
	}


	@Override
	public List<MenuVO> buttons(String roleId) {
		List<Menu> buttons = new ArrayList<>();
		if(Objects.nonNull(roleId)){
			List<Long> roleidList = Func.toLongList(roleId);
			if(Objects.nonNull(roleidList)&&roleidList.size()>0){
				buttons = baseMapper.buttons(roleidList);
			}
		}
		MenuWrapper menuWrapper = new MenuWrapper();
		return menuWrapper.listNodeVO(buttons);
	}

	@Override
	public List<MenuVO> tree() {
		return ForestNodeMerger.merge(baseMapper.tree());
	}
	@Override
	public List<MenuVO> treeByRoleType(int roleType){
		List<MenuVO> resList = new ArrayList<>();
		switch (roleType){
			case -2:
				break;
			case -1:
				break;
			case 0:
				break;
		}
		return resList;
	}

	/**
	 * 获取所有可授权菜单
	 * 1、服务包中包含
	 * 2、公共菜单
	 * @param user
	 * @return
	 */
	@Override
	public List<MenuVO> grantTree(AuthInfo user) {
		AuthInfo authInfo = SecureUtil.getAuthInfo();
		return ForestNodeMerger.merge(baseMapper.grantTreeByEnterprise(Long.valueOf(authInfo.getEnterprise())));
	}

	@Override
	public List<String> roleTreeKeys(String roleIds) {
		List<RoleMenu> roleMenus = roleMenuService.list(Wrappers.<RoleMenu>query().lambda().in(RoleMenu::getRoleId, Func.toLongList(roleIds)));
		return roleMenus.stream().map(roleMenu -> Func.toStr(roleMenu.getMenuId())).collect(Collectors.toList());
	}

	@Override
	public List<Kv> authRoutes(AuthUser user) {
		if (Func.isEmpty(user)) {
			return null;
		}
		List<MenuDTO> routes = baseMapper.authRoutes(Func.toLongList(user.getRoleIdString()));
		List<Kv> list = new ArrayList<>();
		routes.forEach(route -> list.add(Kv.init().set(route.getPath(), Kv.init().set("authority", Func.toStrArray(route.getAlias())))));
		return list;
	}

	@Override
	public List<MenuVO> grantServiceMenuTree(String tenantId) {
		//公共菜单tree和本公司的菜单tree
		List<Menu> menus =new ArrayList<>();
		System.out.println("获取用户 TenantId:"+tenantId);
		menus = getMenuForGrant(tenantId);
		MenuWrapper menuWrapper = new MenuWrapper();
		return ForestNodeMerger.merge(menuWrapper.listNodeVO(menus));
	}

	private List<Menu> getMenuForGrant(String tenantId){
		//获取所有叶节点，然后再依据叶节点组织树，直到根节点。暂时只考虑当前租户的，菜单不存在出售的概念
		//当前租户只能访问自己的系统的菜单。
		List<Long> systemList = new ArrayList<>();
		QueryWrapper<SystemEntity> systemEntityQueryWrapper = new QueryWrapper<>();
		systemEntityQueryWrapper.eq("tenant_id",tenantId).select("id");
		systemList = systemService.listObjs(systemEntityQueryWrapper);
		QueryWrapper<Menu> menuQueryWrapper = new QueryWrapper<>();
		menuQueryWrapper.in("system_id",systemList);
		List<Menu> menuPublicList = baseMapper.selectList(menuQueryWrapper);
		return menuPublicList;
	}
	private List<Long> tenantMenuIds(String tenantId,List<Long> longs) {
		QueryWrapper<SystemEntity> systemEntityQueryWrapper = new QueryWrapper<>();
		systemEntityQueryWrapper.eq("tenant_id", tenantId);//查询本租户菜单
		List<SystemEntity> list = systemService.list(systemEntityQueryWrapper);
		if(list!=null && list.size()>0){
			list.stream().forEach(systemEntity->{
				longs.add(systemEntity.getId());
			});
		}
		return longs;
	}

}
